package com.bilibili.server.utils;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Component
public class RedisUtil {

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Autowired
    private ObjectMapper objectMapper;

    // 简单的布隆过滤器实现（用于防止缓存穿透）
    private static class SimpleBloomFilter {
        private static final int DEFAULT_SIZE = 1000000;
        private static final int DEFAULT_HASH_COUNT = 3;
        private final int size;
        private final int hashCount;

        public SimpleBloomFilter(int size, int hashCount) {
            this.size = size;
            this.hashCount = hashCount;
        }

        public SimpleBloomFilter() {
            this(DEFAULT_SIZE, DEFAULT_HASH_COUNT);
        }

        // 生成哈希值
        private int hash(String str, int seed) {
            int hash = 0;
            for (char c : str.toCharArray()) {
                hash = ((hash << 5) + hash) + c;
                hash = hash & hash; // 转换为32位整数
                hash = Math.abs(hash);
            }
            return (hash + seed) % size;
        }

        // 获取多个哈希位置
        public List<Integer> getHashPositions(String key) {
            List<Integer> positions = new ArrayList<>();
            for (int i = 0; i < hashCount; i++) {
                positions.add(hash(key, i));
            }
            return positions;
        }
    }

    private final SimpleBloomFilter bloomFilter = new SimpleBloomFilter();
    private final Set<Long> pendingViewUpdates = Collections.synchronizedSet(new HashSet<>());

    // 观看次数更新配置
    private static final int BATCH_SIZE = 50;
    private static final long UPDATE_INTERVAL = 600000; // 10分钟
    private static final int MAX_QUEUE_SIZE = 1000;

    static {
        // 可以在这里启动定时任务，定期更新观看次数
    }

    // 生成随机过期时间
    private long getRandomExpire(long baseExpire, long variance) {
        long randomOffset = new Random().nextLong() % (variance * 2);
        return Math.max(60, baseExpire + randomOffset);
    }

    // 设置缓存
    public boolean setCache(String key, Object value, Long expire, boolean useRandomExpire) {
        try {
            ValueOperations<String, String> operations = redisTemplate.opsForValue();
            String serializedValue = objectMapper.writeValueAsString(value);
            
            if (expire != null) {
                long finalExpire = useRandomExpire ? getRandomExpire(expire, 300) : expire;
                operations.set(key, serializedValue, finalExpire, TimeUnit.SECONDS);
            } else {
                operations.set(key, serializedValue);
            }
            
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    public boolean setCache(String key, Object value, Long expire) {
        return setCache(key, value, expire, true);
    }

    // 获取缓存
    public <T> T getCache(String key, Class<T> clazz, boolean useBloomFilterCheck) {
        try {
            if (useBloomFilterCheck && !checkBloomFilter(key)) {
                return null;
            }
            
            ValueOperations<String, String> operations = redisTemplate.opsForValue();
            String value = operations.get(key);
            return value != null ? objectMapper.readValue(value, clazz) : null;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    public <T> T getCache(String key, Class<T> clazz) {
        return getCache(key, clazz, false);
    }

    // 删除缓存
    public boolean deleteCache(String key) {
        try {
            redisTemplate.delete(key);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    // 递增计数器
    public Long incrementCounter(String key, long increment) {
        try {
            return redisTemplate.opsForValue().increment(key, increment);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    // 设置过期时间
    public boolean expire(String key, long seconds) {
        try {
            redisTemplate.expire(key, seconds, TimeUnit.SECONDS);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    // 检查键是否存在
    public boolean exists(String key) {
        try {
            return redisTemplate.hasKey(key);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    // 根据模式删除缓存
    public long deleteCachePattern(String pattern) {
        try {
            Set<String> keys = redisTemplate.keys(pattern);
            if (keys != null && !keys.isEmpty()) {
                redisTemplate.delete(keys);
                return keys.size();
            }
            return 0;
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

    // 添加到布隆过滤器
    public boolean addToBloomFilter(String key) {
        try {
            List<Integer> positions = bloomFilter.getHashPositions(key);
            String filterKey = "bloom_filter:keys";
            
            for (Integer position : positions) {
                redisTemplate.opsForValue().setBit(filterKey, position, true);
            }
            
            redisTemplate.expire(filterKey, 7 * 24 * 60 * 60, TimeUnit.SECONDS); // 7天过期
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    // 检查布隆过滤器
    public boolean checkBloomFilter(String key) {
        try {
            List<Integer> positions = bloomFilter.getHashPositions(key);
            String filterKey = "bloom_filter:keys";
            
            for (Integer position : positions) {
                Boolean bit = redisTemplate.opsForValue().getBit(filterKey, position);
                if (bit == null || !bit) {
                    return false;
                }
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return true; // 失败时默认返回true，不影响主流程
        }
    }

    // 排队观看次数更新
    public void queueViewCountUpdate(Long videoId) {
        if (pendingViewUpdates.size() >= MAX_QUEUE_SIZE) {
            System.out.println("观看次数更新队列已满，丢弃更新请求");
            return;
        }
        pendingViewUpdates.add(videoId);
    }

    // 获取待更新的视频ID列表
    public Set<Long> getPendingViewUpdates() {
        Set<Long> videoIds = new HashSet<>(pendingViewUpdates);
        pendingViewUpdates.clear();
        return videoIds;
    }
    
    // 获取视频观看次数计数器值
    public Integer getVideoViewCount(Long videoId) {
        try {
            String counterKey = "video:view:" + videoId;
            String counterValueStr = redisTemplate.opsForValue().get(counterKey);
            return counterValueStr != null ? Integer.parseInt(counterValueStr) : 0;
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }
    
    // 重置视频观看次数计数器
    public void resetVideoViewCount(Long videoId) {
        try {
            String counterKey = "video:view:" + videoId;
            redisTemplate.opsForValue().set(counterKey, "0");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
